/*
    Priscilla - A library for enocean network access
    Copyright (C) 2012-2013 B. Aigner / R. Wagner

    This program is free software; you can redistribute it and/or 
    modify it under the terms of the GNU General Public License 
    as published by the Free Software Foundation; either version 2 
    of the License, or at your option any later version. 
 
    This program is distributed in the hope that it will be useful, 
    but WITHOUT ANY WARRANTY; without even the implied warranty of 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    GNU General Public License for more details. 
 
    You should have received a copy of the GNU General Public License 
    along with this program; if not, write to the Free Software 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. 
 
    Linking this library statically or dynamically with other modules is 
    making a combined work based on this library. Thus, the terms and 
    conditions of the GNU General Public License cover the whole 
    combination. 
 
    As a special exception, the copyright holders of this library give you 
    permission to link this library with independent modules to produce an 
    executable, regardless of the license terms of these independent 
    modules, and to copy and distribute the resulting executable under terms 
    of your choice, provided that you also meet, for each linked independent 
    module, the terms and conditions of the license of that module. An 
    independent module is a module which is not derived from or based on 
    this library. If you modify this library, you may extend this exception 
    to your version of the library, but you are not obligated to do so. If 
    you do not wish to do so, delete this exception statement from your 
    version. 
*/

package at.technikum_wien.embsys.aat.PriscillaCore.event;

import at.technikum_wien.embsys.aat.PriscillaCore.component.EEP_05_xx_xx;
import at.technikum_wien.embsys.aat.PriscillaCore.component.EEP_07_02_30;
import at.technikum_wien.embsys.aat.PriscillaCore.component.EEP_07_04_01;
import at.technikum_wien.embsys.aat.PriscillaCore.component.EEP_07_06_01;
import at.technikum_wien.embsys.aat.PriscillaCore.component.EEP_07_10_03;
import at.technikum_wien.embsys.aat.PriscillaCore.component.EEP_07_10_04;
import at.technikum_wien.embsys.aat.PriscillaCore.component.EEP_07_10_18;
import at.technikum_wien.embsys.aat.PriscillaCore.enums.BinaryState;
import at.technikum_wien.embsys.aat.PriscillaCore.enums.EventSend;
import at.technikum_wien.embsys.aat.PriscillaCore.enums.FanState;
import at.technikum_wien.embsys.aat.PriscillaCore.enums.FanType;
import at.technikum_wien.embsys.aat.PriscillaCore.link.EnOceanLinkImpl;
import at.technikum_wien.embsys.aat.PriscillaCore.telegram.Telegram;
import org.apache.log4j.Logger;
/**
 * Send event
 * 
 * This event is created to send an event to other enocean receivers.
 * The different constructors are used for different types of events.
 * 
 * @author B. Aigner
 */
public class FrameEventSend {
	
	private EventSend type;
	private String deviceID;
	private float value;
	private BinaryState chA;
	private BinaryState chB;
	private BinaryState chC;
	private BinaryState chD;
	private FanState fanState;
	private FanType fanType;
	private static final Logger log = Logger.getLogger(FrameEventSend.class);

	/**
	 * Create a new event with float data payload
	 * 
	 * @param event Event type
	 * @param deviceID device ID for sending
	 * @param data Payload
	 */
	public FrameEventSend(EventSend event, String deviceID, float data) {
		super();
		if(event == EventSend.BINARY_EVENT) this.type = EventSend.INVALID;
		if(event == EventSend.FAN_EVENT) this.type = EventSend.INVALID;

		this.value = data;
		this.type = event;
		this.deviceID = deviceID;
	}
	
	/**
	 * Create a new event with binary data payload
	 * 
	 * @param event Event type
	 * @param deviceID device ID for sending
	 * @param channelA Channel A binary state
	 * @param channelB Channel B binary state
	 * @param channelC Channel C binary state
	 * @param channelD Channel D binary state
	 */
	public FrameEventSend(EventSend event, String deviceID, BinaryState channelA, BinaryState channelB, BinaryState channelC, BinaryState channelD) {
		super();
		if(event != EventSend.BINARY_EVENT) this.type = EventSend.INVALID;
		
		this.chA = channelA;
		this.chB = channelB;
		this.chC = channelC;
		this.chD = channelD;
		this.type = event;
		this.deviceID = deviceID;
	}
	
	/**
	 * Create a new event with fan data payload
	 * 
	 * @param event Event type
	 * @param deviceID device ID for sending
	 * @param fanstate Actual state of the fan
	 * @param fantype Type of the fan state (3 or 5 stages)
	 */
	public FrameEventSend(EventSend event, String deviceID, FanState fanstate, FanType fantype) {
		super();
		if(event != EventSend.FAN_EVENT) this.type = EventSend.INVALID;
		
		this.fanState = fanstate;
		this.fanType = fantype;
		this.type = event;
		this.deviceID = deviceID;
	}

	/**
	 * Create a new telegram from this event
	 * 
	 * This method creates a new telegram for sending from this event.
	 * Differed by the event types, different components are used for
	 * the creation.
	 * 
	 * @return Telegram representation of this event
	 */
	public Telegram getTelegram() {
		switch(type) {
		case BINARY_EVENT: //create a RPS telegram with ORG 05 (binary switch)
			EEP_05_xx_xx data_binary = new EEP_05_xx_xx(deviceID);
			data_binary.setContactA(this.chA);
			data_binary.setContactB(this.chB);
			data_binary.setContactC(this.chC);
			data_binary.setContactD(this.chD);
			
			return data_binary.getTelegram();
			
		case TEMPERATURE_EVENT: //create a 4BS telegram with a temperature sensor
			EEP_07_02_30 data_temp = new EEP_07_02_30(deviceID);
			
			data_temp.setTemperature(this.value);
			
			return data_temp.getTelegram();
			
		case FAN_EVENT: //create a 4BS telegram with a room operating panel, the other data is left empty
			switch(this.fanType) {
			case TYPE3:
				EEP_07_10_04 data_fan3 = new EEP_07_10_04(deviceID);
				
				data_fan3.setFanspeed(this.fanState);
				
				return data_fan3.getTelegram();
			case TYPE5:
				EEP_07_10_18 data_fan5 = new EEP_07_10_18(deviceID);
				
				data_fan5.setFanspeed(this.fanState);
				
				return data_fan5.getTelegram();
			default:
				return null;
			}
			
		case ILLUMINATION_EVENT: //create a 4BS telegram with an illumination sensor
			EEP_07_06_01 data_illumination = new EEP_07_06_01(deviceID);
			
			data_illumination.setIllumination(this.value);
			
			return data_illumination.getTelegram();
			
		case HUMIDITY_EVENT: //create a 4BS telegram with a humdity sensor
			EEP_07_04_01 data_humidity = new EEP_07_04_01(deviceID);
			
			data_humidity.setTemperatureAvailable(false);
			data_humidity.setHumidity(this.value);
			
			return data_humidity.getTelegram();
			
		case SETPOINT_EVENT: //create a 4BS telegram with a room operating panel with set point control
			EEP_07_10_03 data_setpoint = new EEP_07_10_03(deviceID);
			
			data_setpoint.setSetPoint(this.value);
			data_setpoint.setTemperature(0);
			
			return data_setpoint.getTelegram();
			
		case INVALID: //invalid event type/ constructor combination, print out error message
			log.error("Error: wrong combination of event type and constructor while sending");
			return null;
		default: //invalid event
			log.error("Error: unknown event, could not send it");
			return null;
		}
	}

}
